import axios from 'axios'
import QS from 'qs' // 引入qs模块，用来序列化post类型的数据，
import {
  Loading,
  Message
} from 'element-ui' // element-ui
import store from '@store/index'
import router from '@router/index'
import Utils from '@utils/index'
import HttpRequest from '@config/http-request'
import messages from '@plugins/i18n/index'

class Server {
  constructor() {
    this.Loading = null
  }

  checkStatus(response) {
    const status = response.status || -1000 // -1000 自己定义，连接错误的status
    const data = response.data
    const {
      stateName,
      successCode,
      successCodeList
    } = HttpRequest

    if ((status >= 200 && status < 300) || status === 304 || successCodeList.includes(data[stateName])) {
      if (data[stateName] !== successCode && !successCodeList.includes(data[stateName]) && response.config.responseType !== 'blob') {
        return {
          status,
          errorState: true,
          data: response,
          msg: this.messageText(data[stateName], response)
        }
      } else if (response.config.responseType === 'blob' && !successCodeList.includes(data[stateName]) && data.type === 'application/json') {
        const self = this
        return new Promise((resolve, reject) => {
          var reader = new FileReader()
          reader.readAsText(response.data, 'utf-8')
          reader.onload = function () {
            response.data = JSON.parse(reader.result)
            if (response.data) {
              resolve({
                status,
                errorState: true,
                data: response,
                msg: self.messageText(0, response)
              })
            } else {
              // prefer-promise-reject-errors
              reject(response)
            }
          }
        })
      } else {
        // 如果http状态码正常，则直接返回数据
        if (data[stateName] === 403) {
          this.messageText(data[stateName], response)
        }
        return response.data
      }
    } else {
      return {
        status,
        errorState: true,
        msg: this.messageText(data[stateName], response)
      }
    }
  }

  messageText(status, response) {
    const msg = response.data.message || response.data.Message
    let errorInfo = ''
    switch (status) {
      case -1:
        errorInfo = msg || messages.t('message.http.fail')
        break
      case 400:
        errorInfo = msg || messages.t('message.http.400')
        break
      case 401:
        errorInfo = msg || messages.t('message.http.403')
        Utils.localStorage.clear()
        Utils.sessionStorage.clear()
        Utils.token.remove()
        // eslint-disable-next-line no-case-declarations
        const dialogList = document.querySelectorAll('.el-dialog__wrapper')
        if (dialogList.length > 0) {
          for (let index = 0; index < dialogList.length; index++) {
            document.body.removeChild(dialogList[index])
          }
        }

        if (!Utils.getUrlRouter().includes('login')) {
          router.replace({ name: 'Login' })
        }
        break
      case 404:
        errorInfo = msg || messages.t('message.http.404')
        break
      case 405:
        errorInfo = msg || messages.t('message.http.405')
        break
      case 408:
        errorInfo = msg || messages.t('message.http.408')
        break
      case 500:
        errorInfo = msg || messages.t('message.http.500')
        break
      case 501:
        errorInfo = msg || messages.t('message.http.501')
        break
      case 502:
        errorInfo = msg || messages.t('message.http.502')
        break
      case 503:
        errorInfo = msg || messages.t('message.http.503')
        break
      default:
        errorInfo = msg || messages.t('message.http.default')
    }
    Message.error(errorInfo)
    return errorInfo
  }

  setInterceptors(instance, options) {
    // request请求拦截器
    instance.interceptors.request.use(
      config => {
        if (options.loading) {
          this.Loading = Loading.service()
        }

        if (store.getters.token) {
          config.headers.token = store.getters.token
        } else {
          config.headers.token = ''
        }
        if (store.getters.lang === 'zh') {
          config.headers.language = 'zh_cn'
        } else {
          config.headers.language = 'en_us'
        }
        if (JSON.stringify(options.headers) !== '{}') { // 自定义请求头
          config.headers = Object.assign({ Authorization: config.headers.Authorization }, options.headers)
        } else {
          config.headers['Content-Type'] = HttpRequest.contentType
        }
        if (options.responseType) config.responseType = options.responseType
        return Promise.resolve(config)
      },
      error => {
        if (options.loading) {
          this.Loading.close()
        }
        Promise.reject(error)
      }
    )

    // response 响应拦截器
    instance.interceptors.response.use(
      async response => {
        if (options.loading) {
          this.Loading.close()
        }
        if (response.headers['content-type'] === 'application/vnd.ms-excel;charset=utf-8' || response.headers['content-type'] === 'application/pdf') {
          return Promise.resolve(response.data)
        }
        const { errorState } = await this.checkStatus(response)
        if (errorState) {
          return Promise.reject(response.data)
        } else {
          const result = response.data
          let responseData = result.data

          // eslint-disable-next-line no-prototype-builtins
          if (responseData && responseData.hasOwnProperty('records')) { // 分页
            const obj = JSON.parse(JSON.stringify(responseData))
            obj.data = obj.records
            obj.size = Number(obj.pageSize)
            obj.total = Number(obj.total)
            obj.current = Number(obj.pageIndex)
            delete obj.records
            responseData = obj
          }
          return Promise.resolve(responseData)
        }
      },
      error => {
        if (options.loading) {
          this.Loading.close()
        }
        if (error.response) {
          return Promise.reject(this.checkStatus(error.response))
        } else {
          if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
            error.msg = messages.t('message.http.timeOut')
            Message({
              message: messages.t('message.http.timeOut'),
              type: 'warning'
            })
            return Promise.reject(error)
          } else {
            if (typeof error.message.message !== 'undefined') {
              Message({
                message: error.message.message,
                type: 'warning'
              })
            } else {
              Message.error(error.message)
            }
            return Promise.reject(error)
          }
        }
      }
    )
  }

  request(options) {
    // 每次请求都会创建新的axios实例。
    const instance = axios.create()
    const CancelToken = axios.CancelToken
    const config = { // 将用户传过来的参数与公共配置合并。
      ...options,
      baseURL: process.env.VUE_APP_BASE_URL,
      timeout: HttpRequest.timeout,
      crossDomain: HttpRequest.crossDomain, // 设置cross跨域
      withCredentials: HttpRequest.withCredentials, // 设置cross跨域 并设置访问权限 允许跨域携带cookie信息
      transformRequest: [
        function (data) {
          if (Object.prototype.toString.call(data) === '[object FormData]') {
            return data
          }
          data = JSON.stringify(data)
          return data
        }
      ]
    }
    // 配置拦截器
    this.setInterceptors(instance, options)
    return instance(config) // 返回axios实例的执行结果
  }

  get(url, loading, data, headers, responseType) {
    let urlData = ''
    if (data) {
      Object.keys(data).forEach(key => {
        urlData = data[key]
      })
    }
    return this.request({
      method: 'get',
      url: url + '/' + urlData,
      loading: loading,
      headers: headers,
      responseType: responseType
      // params: data
    })
  }

  post(url, loading, data, headers, responseType) {
    return this.request({
      method: 'post',
      url: url,
      loading: loading,
      data: data,
      headers: headers,
      responseType: responseType
    })
  }

  delete(url, loading, data, headers, responseType) {
    return this.request({
      method: 'delete',
      url: url,
      loading: loading,
      data: data,
      headers: headers,
      responseType: responseType
    })
  }

  put(url, loading, data, headers, responseType) {
    return this.request({
      method: 'put',
      url: url,
      loading: loading,
      data: data,
      headers: headers,
      responseType: responseType
    })
  }
}


export default new Server()
